package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.ProcessInstanceStatusEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.TaskLinkStatusEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.TaskCreatedPostProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.SpringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowParticipantInfoVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowProcessInstanceTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowParticipantRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowProcessInstanceTraceRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskTraceRepository;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Objects;

/**
 * @author lilh
 * @date 2021/1/6 下午5:20
 */
@Service
@Order(20)
public class RecordTaskTracePostProcessor implements TaskCreatedPostProcessor {

    @Autowired
    private FlowParticipantRepository participantRepository;

    @Autowired
    private UserService userService;

    @Override
    public void process(TaskEntity taskEntity) {
        this.insertTaskTrace(taskEntity);
    }

    private void insertTaskTrace(TaskEntity taskEntity) {
        FlowTaskTraceVo taskTrace = new FlowTaskTraceVo();
        taskTrace.setTaskId(taskEntity.getId());
        taskTrace.setTaskName(taskEntity.getName());
        taskTrace.setActivityId(taskEntity.getTaskDefinitionKey());
        taskTrace.setLinkStatus(TaskLinkStatusEnum.TODO.getCode());
        taskTrace.setStatus(ProcessInstanceStatusEnum.NORMAL.getCode());
        taskTrace.setProcessInstanceId(taskEntity.getProcessInstanceId());
        taskTrace.setFormKey(taskEntity.getFormKey());
        taskTrace.setCategory(taskEntity.getCategory());
        taskTrace.setFlag(0);
        taskTrace.setCreateTime(new Date());
        taskTrace.setUpdateTime(taskTrace.getCreateTime());
        resolveAssignee(taskEntity, taskTrace);
        resolveProcessInstanceRel(taskTrace, taskEntity.getProcessInstanceId());
        taskTrace.setParentId(resolveParentId(taskEntity));
        SpringUtils.getBean(FlowTaskTraceRepository.class).insertTaskTrace(taskTrace);
    }

    private String resolveParentId(TaskEntity taskEntity) {
        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager().findById(taskEntity.getExecutionId());
        if (Objects.nonNull(execution)) {
            ExecutionEntity parent = execution.getParent();
            if (Objects.nonNull(parent) && parent.isMultiInstanceRoot()) {
                return parent.getId();
            }
        }
        return null;
    }

    private void resolveProcessInstanceRel(FlowTaskTraceVo taskTrace, String processInstanceId) {
        FlowProcessInstanceTraceRepository processInstanceTraceService = SpringUtils.getBean(FlowProcessInstanceTraceRepository.class);
        FlowProcessInstanceTraceVo piTrace = processInstanceTraceService.getProcessInstanceTraceByProcessInstanceId(processInstanceId);
        if (Objects.nonNull(piTrace)) {
            taskTrace.setAppId(piTrace.getAppId());
            taskTrace.setBusiId(piTrace.getBusiId());
            taskTrace.setModelName(piTrace.getModelName());
            taskTrace.setSerialNum(piTrace.getSerialNum());
            taskTrace.setModelKey(piTrace.getModelKey());
            taskTrace.setTenantId(piTrace.getTenantId());
        }
    }

    private void resolveAssignee(TaskEntity taskEntity, FlowTaskTraceVo taskTrace) {
        if (Objects.nonNull(taskEntity.getAssignee())) {
            taskTrace.setOperatorCode(taskEntity.getAssignee());
            User user = userService.getSingleUser(taskEntity.getAssignee());
            if (Objects.nonNull(user)){
                taskTrace.setOperator(user.getUserName());

                FlowParticipantInfoVo participant = new FlowParticipantInfoVo();
                participant.setParticipantId(taskEntity.getAssignee());
                participant.setParticipantType("STA");
                participant.setParticipantName(user.getUserName());
                participant.setCreateTime(new Date());
                participant.setUpdateTime(new Date());
                participantRepository.insertParticipantInfo(participant);
            }
        }
    }

}
